/*
 * Copyright (C) 2011 Emmanuel Tourdot
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * $Id$
 */
package org.etourdot.xinclude.xpointer;

import com.google.common.base.Strings;
import net.sf.saxon.s9api.*;

import javax.xml.namespace.QName;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
import java.io.Reader;
import java.io.Writer;


/**
 * @author Emmanuel Tourdot
 */
public final class PointerPart implements PointerHandler
{
    private final static String XPOINTER = "xpointer";
    private final QName schemeName;
    private final String schemeData;
    private final String localName;
    private XPointerContext xpointerContext;

    public PointerPart(final String localName)
    {
        this.localName = localName;
        this.schemeName = null;
        this.schemeData = null;
    }

    public PointerPart(final QName schemeName, final String schemeData)
    {
        this.localName = null;
        this.schemeName = schemeName;
        this.schemeData = schemeData;
    }

    public void setContext(final XPointerContext xpointerContext)
    {
        this.xpointerContext = xpointerContext;
    }

    @Override
    public void parse(Reader reader, Writer writer) throws XPointerException
    {
        final Processor processor = xpointerContext.getConfiguration().getProcessor();
        final XQueryCompiler compiler = processor.newXQueryCompiler();
        compiler.declareNamespace("xsd", "http://www.w3.org/2001/XMLSchema");
        try
        {
            final XQueryExecutable executable;
            if (Strings.isNullOrEmpty(localName))
            {
                if (XPOINTER.equalsIgnoreCase(schemeName.getLocalPart()))
                {
                    executable = compiler.compile("<S>{" + schemeData + "}</S>");
                }
                else
                {
                    return;
                }
            }
            else
            {
                executable = compiler.compile("<S>{//*[@id='" + localName + "']}</S>");
            }
            final XQueryEvaluator evaluator = executable.load();
            evaluator.setSource(new StreamSource(reader));
            evaluator.run(new Serializer(writer));
        }
        catch (final SaxonApiException e)
        {
            throw new XPointerException(e);
        }
    }

    @Override
    public void parse(final String systemId, final Writer writer) throws XPointerException
    {
        final Processor processor = xpointerContext.getConfiguration().getProcessor();
        final XQueryCompiler compiler = processor.newXQueryCompiler();
        compiler.declareNamespace("xsd", "http://www.w3.org/2001/XMLSchema");
        try
        {
            final XQueryExecutable executable;
            if (Strings.isNullOrEmpty(localName)) 
            {
                if (XPOINTER.equalsIgnoreCase(schemeName.getLocalPart()))
                {
                    executable = compiler.compile("<S>{" + schemeData + "}</S>");
                }
                else
                {
                    return;
                }
            }
            else
            {
                executable = compiler.compile("<S>{//*[@id='" + localName + "']}</S>");
            }
            final XQueryEvaluator evaluator = executable.load();
            evaluator.setSource(new StreamSource(new File(systemId)));
            evaluator.run(new Serializer(writer));
        }
        catch (final SaxonApiException e)
        {
            throw new XPointerException(e);
        }
    }
}
